package com.tanhua.dubbo.server.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tanhua.dubbo.server.config.HuanXinConfig;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class TokenService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

     @Autowired
     private HuanXinConfig huanXinConfig;

    private static final String REDIS_KEY = "HX_TOKEN";

    /**
     * 获取token，先从redis中获取，如果没有，再去环信接口获取
     *
     * @return
     */
    public String getToken() {
        //1.连接redis获取缓存环信token
        String token = redisTemplate.opsForValue().get(REDIS_KEY);
        //2.查询到直接返回即可
        if (StrUtil.isNotEmpty(token)) {
            return token;
        }

        //3.缓存中没有环信token，调用刷新token方法获取并将token缓存到redis中
        return refreshToken();
    }


    /**
     * 刷新token，请求环信接口，将token存储到redis中
     * @return
     */
    public String refreshToken() {
        //1.定义请求路径
        String targetUrl =huanXinConfig.getUrl() +         //  http://a1.easemob.com/
                huanXinConfig.getOrgName() + "/" +          //  http://a1.easemob.com/1109210525065665
                huanXinConfig.getAppName() + "/token";      //  http://a1.easemob.com/1109210525065665/sy-tanhua/token

        //2.定义请求参数
        Map<String, Object> param = new HashMap<>();
        param.put("grant_type", "client_credentials");
        param.put("client_id", huanXinConfig.getClientId());            //YXA6DblOt6XyTLiZo1Svvxeocg
        param.put("client_secret", huanXinConfig.getClientSecret());    //YXA6vfbPvmvpC8ECb9o-VCh1AvXrkbE
        //3.发送请求
        HttpResponse response = HttpRequest.post(targetUrl)     //设置请求方式、请求地址路径
                .body(JSONUtil.toJsonStr(param))                //设置请求体，将map集合转换为json格式字符串
                .timeout(20000)                                 //请求超时时间
                .execute();                                     //执行该操作

        //4.响应失败
        if (!response.isOk()) {
            /*返回值400，表示 client_id 或 client_secret 错误
            如果返回结果是429、503或者其他5xx，有可能代表该接口被限流了，请稍微暂停一下并重试*/
            log.error("刷新token失败~~~ ");
            return null;
        }

        //5.响应成功，解析json
        //5.1 获取响应体内容
        String jsonBody = response.body();                      //json字符串
        JSONObject jsonObject = JSONUtil.parseObj(jsonBody);    //json字符串 => 对象
        //5.2 获取token信息
        String token = jsonObject.getStr("access_token");
        if (StrUtil.isNotEmpty(token)) {
            //5.3 证明获取到了环信token
            //5.4 将环信token保存到redis中
            //有效时长，相对于官方响应回来的有效时长缩短1小时
            long timeout = jsonObject.getLong("expires_in") - 3600;
            //保存至redis
            redisTemplate.opsForValue().set(REDIS_KEY, token, timeout, TimeUnit.SECONDS);

            return token;
        }

        return null;

    }
}
